package com.lizemin.decorate.filter;

import com.lizemin.decorate.filter.wrapper.XssRequestWrapper;
import com.lizemin.decorate.filter.wrapper.XssResponseWrapper;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

/**
 * @author lzm
 * @date 2025/10/6 12:19
 * @description XSS攻击过滤器
 */
public class XssFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // get请求没有content-type， 对get请求的路径参数进行XSS过滤
        if (HttpMethod.GET.name().equalsIgnoreCase(request.getMethod())) {
            filterXssScript(request, response, filterChain);
            return;
        }
        // 对请求体中的参数进行XSS过滤
        String contentType = request.getContentType();
        if (!StringUtils.hasText(contentType)) {
            filterChain.doFilter(request, response);
            return;
        }
        if (!contentType.contains(MediaType.APPLICATION_JSON_VALUE)) {
            filterChain.doFilter(request, response);
            return;
        }
        filterXssScript(request, response, filterChain);
    }

    /**
     * 对请求体中的参数进行XSS过滤
     *
     * @param request     请求对象
     * @param response    响应对象
     * @param filterChain 过滤器链
     */
    private static void filterXssScript(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        XssRequestWrapper xssRequestWrapper = new XssRequestWrapper(request);
        XssResponseWrapper xssResponseWrapper = new XssResponseWrapper(response);
        filterChain.doFilter(xssRequestWrapper, xssResponseWrapper);
        // 此刻接口已经执行完毕，则开始过滤响应报文中的javascript脚本,并且转义处理后的响应报文返回给前端
        xssResponseWrapper.filterScript();
    }

}
